共计 2641 个字符,预计需要花费 7 分钟才能阅读完成。
引入
查看源码前提 :
- 刚开始阅读一些库的源码的时候, 最好选一些代码量少的先感受一下
- 碰到看不懂的, 我们没必要去死磕, 只看自己能看懂的, 看不懂的忽略
一.django 的两个配置文件
- 一个是暴露给用户可以自定义的配置文件 : 项目根目录下的 setting.py 文件
- 一个是项目默认的配置文件 : 当用户不做任何配置的时候自动加载默认配置
二. 分析源码解决疑问
- 为什么配置文件必须是大写
- 为什么当前用户配置了就使用用户配置的, 不配置就使用默认的
三. 源码分析
1. 突破口 : settings 文件, 将其导入
from django.conf import settings
2.Ctrl + 点击 settings 进入其中
......
settings = LazySettings()
发现它是由 LazySettings 类实例的对象
3. 再点击进入到 LazySettings 类中查看
class LazySettings(LazyObject):
def _setup(self, name=None):
# os.environ 获取环境变量中所有的配置, 相当于一个大字典, 这里取出 ENVIRONMENT_VARIABLE
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
if not settings_module:
......
self._wrapped = Settings(settings_module)
4. 我们先点击 ENVIRONMENT_VARIABLE 进去看看这是个什么
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
翻译是 Django 的配置模板, Django 在启动的时候就会加载这个配置, 我们再去 Django 的启动文件 manage.py 中去看看
5. 进入 manage.py 文件查看相关内容
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
找到这一条, 将
'DJANGO_SETTINGS_MODULE':'mysite.settings'
添加进环境变量配置大字典中
6. 返回到 LazySetting 类当中分析
class LazySettings(LazyObject):
def _setup(self, name=None):
# 这里相当于是 settings_module = 'mysite.settings'
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)
......
# 这里是将 settings_module, 也就是 'mysite.settings' 传入到 Settings 类中实例化得到一个对象
self._wrapped = Settings(settings_module)
7. 我们再点击进入 Settings 类中查看类代码
from django.conf import global_settings
class Settings:
def __init__(self, settings_module):
# update this dict from global settings (but only for ALL_CAPS settings)
# 上面的提示是从全局配置中更新此字典(仅针对所有大写的配置), 那么我们可以知道 global_setting 是一个全局配置文件
for setting in dir(global_settings):
if setting.isupper():
setattr(self, setting, getattr(global_settings, setting))
......
8. 点击 global_settings 进入全局配置文件中查看配置
"""
Default Django settings. Override these with settings in the module pointed to
by the DJANGO_SETTINGS_MODULE environment variable.
"""
# 默认的 Django 设置,用 Django settings 模块环境变量指向的模块中的设置覆盖这些设置
# 意思就是说这是默认的配置文件, 如果你在暴露给用户的 settings 文件中配置了某变量则覆盖这里面的变量
9. 我们再返回 Settings 类分析其代码
class Settings(object):
def __init__(self, settings_module): # 'mysite.settings'
# dir()获取全局配置文件里面所有的变量名, 循环取出来
for setting in dir(global_settings):
if setting.isupper(): # 校验是否是纯大写(这也就是配置变量小写无效)
# getattr()获取全局变量中所有的大写配置的值
# setattr()再将该配置名以及对应的值添加到 Settings 对象中
setattr(self, setting, getattr(global_settings, setting))
# 将 'mysite.settings' 赋值给 self.SETTINGS_MODULE 后面使用
self.SETTINGS_MODULE = settings_module
# importlib 模块: 以字符串的方式导入模块, 也就导入了暴露给用户的配置文件
# from mysite import settings
mod = importlib.import_module(self.SETTINGS_MODULE)
for setting in dir(mod):
if setting.isupper():
# 循环取出暴露给用户配置文件中的所有大写的配置值
setting_value = getattr(mod, setting)
.......
# 然后再将其设置进入 Settings 对象中, 有就覆盖, 没有就添加
setattr(self, setting, setting_value)
通过 Settings 类的源码分析, 我们可以得出这样一个步骤 :
- 先得到全局配置文件中所有的大写的配置, 并将其加入到 Settings 类对象中去
- 然后再获取暴露给用户的 settings 配置中所有大写的值, 并将其也设置进 Settings 类对象中
- 这样一来 Settings 类对象中如果第一次添加的配置名与第二次添加的配置名相同, 就会被第二次的配置覆盖
- Django 启动加载的就是这个 Settings 类对象中所有的配置,
正文完